
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
							   proc.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
													Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "const.h"
#include "protect.h"
#include "tty.h"
#include "console.h"
#include "string.h"
#include "proc.h"
#include "global.h"
#include "proto.h"
#define blockedTimeLimit 10
/**
 * FCFS算法+优先级
 */
PUBLIC PROCESS *ifEmergent()
{
	int isEmergent = 0;
	PROCESS *p = 0;
	for (p = proc_table; p < proc_table + NR_TASKS + NR_PROCS; p++)
	{
		if (p->priorityNow == 0)
		{
			isEmergent = 1;
			break;
		}
	}
	if (isEmergent == 0)
	{
		p = 0;
	}
	return p;
}

PUBLIC void p_process(SEMAPHORE *s)
{
	disable_int();
	// PROCESS *isEmergent = ifEmergent();
	// if (isEmergent && p_proc_ready != isEmergent)
	// {
	// 	// 必须等待，继续睡
	// 	sleep_ms(TIME_SLICE * 2);
	// }
	// else
	// {
	// 	if (isEmergent && p_proc_ready == isEmergent)
	// 	{
	// 		p_proc_ready->priorityNow = 1;
	// 		p_proc_ready->blockedLast = 0;
	// 	}
	// 	s->value--;
	// 	if (s->value < 0)
	// 	{
	// 		p_proc_ready->blocked++;
	// 		s->p_list[s->tail] = p_proc_ready;
	// 		s->tail = (s->tail + 1) % NR_PROCS;
	// 		schedule();
	// 	}
	// }
	s->value--;
	if (s->value < 0)
	{
		p_proc_ready->blocked++;
		s->p_list[s->tail] = p_proc_ready;
		s->tail = (s->tail + 1) % NR_PROCS;
		schedule();
	}
	enable_int();
}

PUBLIC void v_process(SEMAPHORE *s)
{
	disable_int();
	s->value++;
	// 小于等于0表示有进程需要该资源
	if (s->value <= 0)
	{
		// // 根据优先级和FCFS判断
		// PROCESS *p;
		// int ifEmergent = 0;
		// for (p = proc_table; p < proc_table + NR_TASKS + NR_PROCS; p++)
		// {
		// 	if (p->priorityNow == 0)
		// 	{
		// 		p->blocked = 0;
		// 		p->priorityNow = p->realPriority;
		// 		ifEmergent = 1;
		// 		break;
		// 	}
		// }

		// if (ifEmergent == 0)
		// {

		s->p_list[s->head]->blocked--; // 唤醒最先进入队列的进程
		s->head = (s->head + 1) % NR_PROCS;

		// }
	}
	enable_int();
}

/*======================================================================*
							  schedule
 *======================================================================*/
PUBLIC void schedule()
{
	PROCESS *p;
	int greatest_ticks = 0;
	while (!greatest_ticks)
	{

		int ifEmergent = 0;

		for (p = proc_table; p < proc_table + NR_TASKS + NR_PROCS; p++)
		{
			// 如果Blocked达到一定时间，则优先级变换
			if (p->blocked)
			{
				p->blockedLast++;
			}
			if (p->blockedLast >= blockedTimeLimit)
			{
				p->priorityNow = 0; // 最高优先级
			}
			// 正在睡眠/阻塞的进程不会被执行（也就是不会被分配时间片）
			// 并且正在运行的程序，不必更改状态（因此也跳过）
			if (p->sleeping > 0 || p->blocked)
				continue;

			if (p->ticks > greatest_ticks)
			{
				greatest_ticks = p->ticks;
				p_proc_ready = p;
			}
		}
		// 如果都是0，那么需要重设ticks
		if (!greatest_ticks)
		{
			for (p = proc_table; p < proc_table + NR_TASKS + NR_PROCS; p++)
			{
				if (p->ticks > 0)
					continue; // >0 还进入这里只能说明它被阻塞了
				p->ticks = p->priority;
			}
		}
	}

	// p_proc_ready++;
	// if (p_proc_ready->blocked)
	// {
	// 	p_proc_ready++;
	// }
	// if (p_proc_ready >= proc_table + NR_TASKS + NR_PROCS)
	// {
	// 	p_proc_ready = proc_table;
	// }
}

/*======================================================================*
						   sys_get_ticks
 *======================================================================*/
PUBLIC int sys_get_ticks()
{
	return ticks;
}

PUBLIC void sys_sleep(int milli_sec)
{
	int ticks = milli_sec / 1000 * HZ * 10;
	p_proc_ready->sleeping = ticks;
	schedule();
}

PUBLIC void sys_write_str(char *buf, int len)
{
	CONSOLE *p_con = console_table;
	for (int i = 0; i < len; i++)
	{
		out_char(p_con, buf[i]);
	}
}
/*======================================================================*
						   show_state
 *======================================================================*/
PUBLIC void show_state_process()
{
	PROCESS *p;
	for (p = proc_table + 1; p < proc_table + NR_TASKS + NR_PROCS - 1; p++)
	{
		if (p->ifrunning == 1)
		{
			printf("%c%c ", GREEN, 'O');
		}
		else if (p->blocked == 1)
		{
			printf("%c%c ", 01, 'X');
		}
		else
		{
			printf("%c%c ", 3, 'Z');
		}
	}
}
/*======================================================================*
						   work
 *======================================================================*/
PUBLIC void work_process(int slices)
{

	p_proc_ready->ifrunning = 1;
}
/*======================================================================*
						   sleep
 *======================================================================*/
PUBLIC void sleep_process()
{
	p_proc_ready->ifrunning = 0;
}